home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rsynth / src / sayNODICT.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  8.0 KB  |  408 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include "proto.h"
  7. #include "parwave.h"
  8. #include "hplay.h"
  9. #include "dict.h"
  10. #include "ASCII.h"
  11. #include "darray.h"
  12. #include "holmes.h"
  13. #include "phtoelm.h"
  14. #include "text.h"
  15. #include "say.h"
  16.  
  17. int synthesis_model = ALL_PARALLEL;
  18. long nfcascade = 4;
  19. long nspfr;
  20. long sigmx;
  21. long warnsw, dispt, disptcum;
  22. int bDebug = 0;
  23. FILE *debug1, *debug2;
  24.  
  25. dict_t *dict;
  26.  
  27. unsigned
  28. spell_out(word, n, phone)
  29. char *word;
  30. int n;
  31. darray_ptr phone;
  32. {
  33.  unsigned nph = 0;
  34.  fprintf(stderr, "Spelling '%.*s'\n", n, word);
  35.  while (n-- > 0)
  36.   {
  37.    nph += xlate_string(ASCII[toascii(*word++)], phone);
  38.   }
  39.  return nph;
  40. }
  41.  
  42. int
  43. suspect_word(s, n)
  44. char *s;
  45. int n;
  46. {
  47.  int i = 0;
  48.  int seen_lower = 0;
  49.  int seen_upper = 0;
  50.  int seen_vowel = 0;
  51.  int last = 0;
  52.  for (i = 0; i < n; i++)
  53.   {
  54.    char ch = *s++;
  55.    if (i && last != '-' && isupper(ch))
  56.     seen_upper = 1;
  57.    if (islower(ch))
  58.     {
  59.      seen_lower = 1;
  60.      ch = toupper(ch);
  61.     }
  62.    if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'Y')
  63.     seen_vowel = 1;
  64.    last = ch;
  65.   }
  66.  return !seen_vowel || (seen_upper && seen_lower) || !seen_lower;
  67. }
  68.  
  69. static unsigned xlate_word PROTO((char *word, int n, darray_ptr phone));
  70.  
  71.  
  72. static unsigned
  73. xlate_word(word, n, phone)
  74. char *word;
  75. int n;
  76. darray_ptr phone;
  77. {
  78.  unsigned nph = 0;
  79.  if (*word != '[')
  80.   {
  81.    if (dict)
  82.     {
  83.      dictrec_ptr p = spell_find(dict, word, n);
  84.      if (p)
  85.       {
  86.        char *s = p->pronounce;
  87.        char *e = p->pronounce + sizeof(p->pronounce);
  88. #if 0
  89.        fprintf(stderr, "Dict '%.*s'\n", n, word);
  90. #endif
  91.        /* may need to modify dictionary's idea of phonemes here,
  92.           as (for example) final :-> /'faInl/ does not work as it stands.
  93.           This is probably part of a deeper problem concerning
  94.           which allophone to use for a particular phoneme in context.
  95.        */
  96.        while (e > s && isspace(e[-1]))
  97.         e--;
  98.        while (s < e)
  99.         phone_append(phone, *s++);
  100.        phone_append(phone, ' ');
  101.        return nph + 1;
  102.       }
  103.      else
  104.       {
  105.        /* If supposed word contains '.' or '-' try breaking it up...*/
  106.        char *h = word;
  107.        while (h < word + n)
  108.         {
  109.          if (*h == '.' || *h == '-')
  110.           {
  111.        fprintf(stderr,"XLATE 1\n");
  112.            nph += xlate_word(word, h++ - word, phone);
  113.            nph += xlate_word(h, word + n - h, phone);
  114.            return nph;
  115.           }
  116.          else
  117.           h++;
  118.         }
  119.       }
  120.     }
  121.    if (suspect_word(word, n) && n > 1) {
  122.     fprintf(stderr,"SPELLOUT 1\n");
  123.     return spell_out(word, n, phone);
  124.    }
  125.    else
  126.     {
  127.      fprintf(stderr, "Guess '%.*s'\n", n, word);
  128.      nph += NRL(word, n, phone);
  129.     }
  130.   }
  131.  else
  132.   {
  133.    if ((++word)[(--n) - 1] == ']')
  134.     n--;
  135.    while (n-- > 0)
  136.     {
  137.      phone_append(phone,*word++);
  138.      nph++;
  139.     }
  140.   }
  141.  phone_append(phone, ' ');
  142.  return nph + 1;
  143. }
  144.  
  145.  
  146. void
  147. say_phones(phone, len)
  148. char *phone;
  149. int len;
  150. {
  151.  darray_t elm;
  152.  unsigned frames;
  153.  darray_init(&elm, sizeof(char), len);
  154.  if ((frames = phone_to_elm(phone, len, &elm)))
  155.   {
  156.    unsigned max_samples = frames * nspfr;
  157.    short *samp = (short *) malloc(sizeof(short) * max_samples);
  158.    printf("%.*s\n", len, phone);
  159.    if (samp)
  160.     {
  161.      unsigned nsamp = holmes(elm.items, (unsigned char *) darray_find(&elm, 0),
  162.                              max_samples, samp);
  163.      audio_play(nsamp, samp);
  164.      free(samp);
  165.     }
  166.   }
  167.  darray_free(&elm);
  168. }
  169.  
  170. unsigned
  171. xlate_string(string, phone)
  172. char *string;
  173. darray_ptr phone;
  174. {
  175.  unsigned nph = 0;
  176.  char *s = string;
  177.  char ch;
  178.  while (isspace(ch = *s))
  179.   s++;
  180.  while ((ch = *s))
  181.   {
  182.    char *word = s;
  183.    if (isalpha(ch))
  184.     {
  185.      while (isalpha(ch = *s) || ((ch == '\'' || ch == '-' || ch == '.') && isalpha(s[1])))
  186.       s++;
  187.      if (!ch || isspace(ch) || ispunct(ch) || (isdigit(ch) && !suspect_word(word, s - word))) {
  188.          fprintf(stderr,"XLATE 2\n");
  189.          nph += xlate_word(word, s - word, phone);
  190.          fprintf(stderr,"RETURNED 2\n");
  191.      
  192.      }
  193.      else
  194.       {
  195.        while ((ch = *s) && !isspace(ch) && !ispunct(ch))
  196.         s++;
  197.        fprintf(stderr,"SPELLOUT 2\n");
  198.        nph += spell_out(word, s - word, phone);
  199.       }
  200.     }
  201.    else if (isdigit(ch) || (ch == '-' && isdigit(s[1])))
  202.     {
  203.      int sign = (ch == '-') ? -1 : 1;
  204.      long value = 0;
  205.      if (sign < 0)
  206.       ch = *++s;
  207.      while (isdigit(ch = *s))
  208.       {
  209.        value = value * 10 + ch - '0';
  210.        s++;
  211.       }
  212.      if (ch == '.' && isdigit(s[1]))
  213.       {
  214.        word = ++s;
  215.        nph += xlate_cardinal(value * sign, phone);
  216.        nph += xlate_string("point", phone);
  217.        while (isdigit(ch = *s))
  218.         s++;
  219.        fprintf(stderr,"SPELLOUT 3\n");
  220.        nph += spell_out(word, s - word, phone);
  221.       }
  222.      else
  223.       {
  224.        /* check for ordinals, date, time etc. can go in here */
  225.        nph += xlate_cardinal(value * sign, phone);
  226.       }
  227.     }
  228.    else if (ch == '[' && strchr(s,']'))
  229.     {char *word = s;
  230.      while (*s && *s++ != ']') {
  231.       /* nothing */;
  232.        fprintf(stderr,"XLATE 3\n");
  233.        nph += xlate_word(word, s - word, phone);
  234.      }
  235.     }
  236.    else if (ispunct(ch))
  237.     {
  238.      switch (ch)
  239.       {
  240.         /* On end of sentence flush the buffer ... */
  241.        case '!':
  242.        case '?':
  243.        case '.':
  244.         if ((!s[1] || isspace(s[1])) && phone->items)
  245.          {
  246.           say_phones((char *) darray_find(phone, 0), phone->items);
  247.           phone->items = 0;
  248.          }
  249.         s++;
  250.         phone_append(phone, ' ');
  251.         break;
  252.        case '"':               /* change pitch ? */
  253.        case ':':
  254.        case '-':
  255.        case ';':
  256.        case ',':
  257.        case '(':
  258.        case ')':
  259.         s++;
  260.         phone_append(phone, ' ');
  261.         break;
  262.        case '[':  
  263.         {char *e = strchr(s,']');
  264.          if (e)
  265.           {
  266.            s++;
  267.            while (s < e)
  268.             phone_append(phone,*s++);
  269.            s = e+1;
  270.            break;
  271.           }
  272.         }
  273.        default:
  274.         fprintf(stderr,"SPELLOUT 4\n");
  275.         nph += spell_out(word, 1, phone);
  276.         s++;
  277.         break;
  278.       }
  279.     }
  280.    else
  281.     {
  282.      while ((ch = *s) && !isspace(ch))
  283.       s++;
  284.      fprintf(stderr,"SPELLOUT 5\n");
  285.      nph += spell_out(word, s - word, phone);
  286.     }
  287.    while (isspace(ch = *s))
  288.     s++;
  289.   }
  290.  return nph;
  291. }
  292.  
  293. char *
  294. concat_args(argc, argv)
  295. int argc;
  296. char *argv[];
  297. {
  298.  int len = 0;
  299.  int i;
  300.  char *buf;
  301.  for (i = 1; i < argc; i++)
  302.   len += strlen(argv[i]) + 1;
  303.  buf = (char *) malloc(len);
  304.  if (buf)
  305.   {
  306.    char *d = buf;
  307.    for (i = 1; i < argc;)
  308.     {
  309.      char *s = argv[i++];
  310.      while (*s)
  311.       *d++ = *s++;
  312.      if (i < argc)
  313.       *d++ = ' ';
  314.      else
  315.       *d = '\0';
  316.     }
  317.   }
  318.  return buf;
  319. }
  320.  
  321. void
  322. say_string(s)
  323. char *s;
  324. {
  325.  darray_t phone;
  326.  darray_init(&phone, sizeof(char), 128);
  327.  xlate_string(s, &phone);
  328.  if (phone.items)
  329.   say_phones((char *) darray_find(&phone, 0), phone.items);
  330.  darray_free(&phone);
  331. }
  332.  
  333. extern int darray_fget PROTO((FILE *f, darray_ptr p));
  334.  
  335. int
  336. darray_fget(f, p)
  337. FILE *f;
  338. darray_ptr p;
  339. {
  340.  int ch;
  341.  while ((ch = fgetc(f)) != EOF)
  342.   {
  343.    /*
  344.     *  Switch to lower so a mess isnt made : Benoist 94
  345.     *
  346.     */
  347.     ch = tolower(ch);
  348.    phone_append(p, ch);
  349.    if (ch == '\n')
  350.     break;
  351.   }
  352.  phone_append(p, '\0');
  353.  return p->items - 1;
  354. }
  355.  
  356. extern void say_file PROTO((FILE *f));
  357.  
  358. void
  359. say_file(f)
  360. FILE *f;
  361. {
  362.  darray_t line;
  363.  darray_t phone;
  364.  darray_init(&line, sizeof(char), 128);
  365.  darray_init(&phone, sizeof(char), 128);
  366.  while (darray_fget(f, &line))
  367.   {
  368.    xlate_string((char *) darray_find(&line, 0), &phone);
  369.    line.items = 0;
  370.   }
  371.  if (phone.items)
  372.   say_phones((char *) darray_find(&phone, 0), phone.items);
  373.  darray_free(&phone);
  374.  darray_free(&line);
  375. }
  376.  
  377. int main PROTO((int argc, char *argv[], char *env[]));
  378.  
  379. int
  380. main(argc, argv, env)
  381. int argc;
  382. char *argv[];
  383. char *env[];
  384. {
  385.  dict_t d;
  386.  argc = audio_init(argc, argv);
  387.  argc = init_synth(argc, argv);
  388.  argc = init_holmes(argc, argv);
  389.  if (dict_init(&d, NULL))
  390.   dict = &d;
  391.  if (argc > 1)
  392.   {
  393.    char *s = concat_args(argc, argv);
  394.    if (s)
  395.     {
  396.      say_string(s);
  397.      free(s);
  398.     }
  399.   }
  400.  else
  401.   say_file(stdin);
  402.  audio_term();
  403.  term_holmes();
  404.  if (dict)
  405.   dict_term(dict);
  406.  return (0);
  407. }
  408.